/*
 * @Author: HuangBingQuan <17671241237@163.com>
 * @Date: 2024-03-09 12:09:24
 * @LastEditTime: 2024-04-23 12:34:08
 * @FilePath: /san-zi-qi/src/components/GameComp/GameComp.tsx
 */
import React, { useEffect, useState } from 'react'
import "./GameComp.scss";
import { ChessType, GameStatus } from '../../type/enums';
import { BoardComp } from '../BoardComp/BoardComp';
import GameStatusComp from '../GameStatusComp/GameStatusComp';

// interface IState {
//     cheeses: ChessType[],
//     gameStatus: GameStatus
// }

export const GameComp: React.FC = ()=> {
    const [cheeses, setCheeses] = useState<ChessType[]>([]);
    const [isGameOver, setIsGameOver] = useState<GameStatus>(GameStatus.gaming);
    const [nextChess, setNextChess] = useState<ChessType.red | ChessType.black>(ChessType.black);

    /**
     * 棋子初始化
     */
    const init = ()=> {
        const arr: ChessType[] = [];
        for(let i = 0; i < 10 * 10; i++) {
            arr.push(ChessType.none);
        }
        setCheeses(arr);
        setIsGameOver(GameStatus.gaming);
        setNextChess(ChessType.black);
    }

    /**
     * 处理棋子点击事件（下棋动作)
     * 如果运行该函数说明游戏没有结束，并且点击的位置没有棋子
     * @param index 
     */
    const handleChessClick = (index: number)=> {
        const newCheeses: ChessType[] = [...cheeses];
        newCheeses[index] = nextChess;
        setCheeses(newCheeses);
        setNextChess(nextChess === ChessType.black ? ChessType.red : ChessType.black);
        setIsGameOver(getStatus(newCheeses, index));
    }

    /**
     * 返回一个坐标
     * @param index 点的是哪一颗棋子
     */
    const getPoint = (index: number): number[]=> {
        // 9(9, 0) 18(9, 1) 27(9, 2) 36(9, 3) 
        let x = index % 10;
        let y = Math.floor(index / 10);
        return [x, y]
    }

    /**
     *  二维坐标转一维 
     *  @param xy 点的是哪一颗棋子
     */
    const getIndex = (xy: number[])=> {
        let [x, y] = xy;
        return y * 10 + x;
    }

    // 是否合法
    const isValid = (cheeses: ChessType[], point: number[], color: ChessType, index: number): Boolean=> {
        const rows = cheeses.length / 10;
        const cols = cheeses.length / 10;
        const [x, y] = point;
        const onePoint = getIndex(point);
        console.log("cheeses", cheeses)
        console.log("x", x);
        console.log("y", y);
        console.log("一维点位", onePoint);
        console.log("基础点为颜色", color);
        return x >= 0 && x < rows && y >=0 && y < cols && cheeses[onePoint] === color;
    }

    const createIsWin = (p1Movement: (xy: number[])=> number[], p2Movement: (xy: number[])=> number[])=> {
        return (cheeses: ChessType[], point: number[], color: ChessType, index: number): boolean=> {
            let count:number = 1; // 计数
            let p1 = p1Movement(point);
            let p2 = p2Movement(point);
            while(1) {
                let p1IsValid = false;
                let p2IsValid = false;
                if(isValid(cheeses, p1, color, index)) {
                    count ++;
                    p1IsValid = true;
                    p1 = p1Movement(p1);
                } 
                if(isValid(cheeses, p2, color, index)) {
                    count ++;
                    p2IsValid = true;
                    p2 = p2Movement(p2);
                }
                if(count >= 5) {
                    return true;
                }
                if(!p1IsValid && !p2IsValid) {
                    return false
                }
            }
            return false;
        }
    }

    /**
     * 判断输赢的上下文
     */
    const context = ()=> {
        return new Map([
            // 横向
            [
                "isWinHorizotal", 
                createIsWin(
                    ([x, y])=> [x + 1, y],
                    ([x, y])=> [x - 1, y]
                )
            ],
            // 纵向
            [
                "isWinVertical", 
                createIsWin(
                    ([x, y])=> [x, y + 1],
                    ([x, y])=> [x, y - 1]
                )
            ],
            // 斜
            [
                "isWinSlash", 
                createIsWin(
                    ([x, y])=> [x + 1, y + 1],
                    ([x, y])=> [x - 1, y - 1]
                )
            ],
            // 反斜
            [
                "isWinBackSlash", 
                createIsWin(
                    ([x, y])=> [x + 1, y - 1],
                    ([x, y])=> [x - 1, y - 1]
                )
            ],
        ])
    }

 
    // 获取赢家是红方还是黑方
    const getWinUser = (currentCheeses: ChessType): GameStatus => {
        return currentCheeses === ChessType.red ? GameStatus.redWin : GameStatus.blackWin;
    }

    /**
     * 得到当前游戏状态
     * @param cheeses 新的棋盘
     * @param index 最后一颗棋子的坐标
     */
    const getStatus = (cheeses: ChessType[], index: number): GameStatus=> {
        console.log("棋盘状态", cheeses, index);
        // 判断是否有一方胜利
        const ctx = context();
        const points = getPoint(index);
        let getIsWinHorizotal = ctx.get('isWinHorizotal');
        let getIsWinVertical = ctx.get('isWinVertical');
        let getIsWinSlash = ctx.get('isWinSlash');
        let getIsWinBackSlash = ctx.get('isWinBackSlash');
        console.log("坐标", points);
        // 横向胜利
        // console.log("getIsWinHorizotal(cheeses, points, cheeses[index], index)", getIsWinHorizotal && getIsWinHorizotal(cheeses, points, cheeses[index], index))
        // console.log("isWinVertical(cheeses, points, cheeses[index], index)", getIsWinVertical && getIsWinVertical(cheeses, points, cheeses[index], index))
        // 胜利
        if(
            (getIsWinHorizotal && getIsWinHorizotal(cheeses, points, cheeses[index], index))
            || (getIsWinVertical && getIsWinVertical(cheeses, points, cheeses[index], index))
            || (getIsWinSlash && getIsWinSlash(cheeses, points, cheeses[index], index))
            || (getIsWinBackSlash && getIsWinBackSlash(cheeses, points, cheeses[index], index))
        ) {
            if(cheeses[index] === ChessType.black) {
                return GameStatus.blackWin;
            }else if(cheeses[index] === ChessType.red) {
                return GameStatus.redWin;
            }
        }else if(!cheeses.includes(ChessType.none)){
            return GameStatus.equal;
        }
        // // 游戏正在进行
        return GameStatus.gaming;
    }

    useEffect(()=> {
        init();
    }, [])

    return (
        <div className='game'>
            <GameStatusComp status={isGameOver} next={nextChess}/>
            {/* 棋盘 */}
            <BoardComp chesses={cheeses} isGameOver={isGameOver !== GameStatus.gaming} onClick={i => handleChessClick(i)}/>
            <div style={{ marginTop: '20px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><button onClick={()=> init()}>重新开始</button></div>
        </div>
    )
}